import math
import numpy as np
from scipy.stats import norm,t,f
from math import sqrt
from prettytable import PrettyTable
import matplotlib.pyplot as plt

# Заданные массивы данных X и Y
X = np.array([5.1, 10.4, 12.8, 18.5, 19.4, 20.5, 22.4, 22.9, 25.1])
Y = np.array([260, 243, 240, 222, 225, 227, 210, 180, 155])

# Задание 1 Вычисление коэфицента Пирсона

## Вычисление средних значений
mean_X = sum(X) / len(X)
mean_Y = sum(Y) / len(Y)
sum_sq_dev_X_mass=[]
sum_sq_dev_Y_mass=[]
sum_sq_dev_X=0
sum_sq_dev_Y=0

# Вычисление сумм квадратов отклонений от среднего для X и Y
for x in X:
    sum_sq_dev_X+=(x - mean_X)**2
    sum_sq_dev_X_mass.append(round((x - mean_X)**2,3))
for y in Y:
    sum_sq_dev_Y+=(y - mean_Y)**2
    sum_sq_dev_Y_mass.append(round((y - mean_Y)**2,3))

# print (sum_sq_dev_X_mass)
# print(sum_sq_dev_Y_mass)

# Вычисление суммы произведений отклонений от средних для X и Y
sum_prod_dev=0
sum_prod_dev_mass=[]
for x,y in zip(X,Y):
    sum_prod_dev+=(x - mean_X) * (y - mean_Y)
    sum_prod_dev_mass.append(round((x - mean_X) * (y - mean_Y),3))

# print(sum_prod_dev_mass)

# Вычисление коэффициента корреляции Пирсона
r_xy = sum_prod_dev /sqrt((sum_sq_dev_X) *(sum_sq_dev_Y))

alpha=0.05

Z=(0.5)*math.log((1+r_xy)/(1-r_xy))

z1=Z-(norm.ppf(1-alpha/2)/sqrt(len(X)-3))
z2=Z+(norm.ppf(1-alpha/2)/sqrt(len(X)-3))
# print(norm.ppf(1-alpha/2))

low_bound=(pow(math.e,2*z1)-1)/(pow(math.e,2*z1)+1)
high_bound=(pow(math.e,2*z2)-1)/(pow(math.e,2*z2)+1)

# Вывод результата

table = PrettyTable()
table.field_names = ["Охват населения вакцинации против гриппа(%) в разных райнах города","Заболеваемость гриппом (на 1000 человек)","(x_i-x*)^2","(y_i-y*)^2", "(x_i-x*)(y_i-y*)"]
for i in range(len(X)):
    table.add_row([round(X[i],3),round(Y[i],3),round(sum_sq_dev_X_mass[i],3),round(sum_sq_dev_Y_mass[i],3),round(sum_prod_dev_mass[i],3)])
print (table)

print ("Количество элементов: ",len(X))
print ("X avg:",round(mean_X,3))
print ("Y avg:",mean_Y)
print ("Q(X)",round(sum_sq_dev_X,3))
print ("Q(Y)",round(sum_sq_dev_Y,3))
print ("Q(XY)",round(sum_prod_dev,3))
print("Коэффициент Пирсона (r_xy):", round(r_xy,3))
if r_xy<0:
    print ("Так как R_xy <0 следовательно связь будет оцениваться как обратная")
else:
    print("Так как R_xy >0 следовательно связь будет оцениваться как прямая")

if abs(r_xy)>0.7:
    print ('Cила связи сильная так как R_xy >0.7')
elif abs(r_xy)>0.3 and abs(r_xy)<0.7:
    print ("Cила связи умеренная так как R_xy <0.7 и <0.3")
elif abs(r_xy)<0.3:
    print ("Cила связи слабая так как R_xy <0.3")
print("Доверительный интервал для коэфицента Пирсона будет равен [",low_bound,',',high_bound,']')
print ('Z:',round(Z,3))
print ('z1:',round(z1,3))
print ('z2:',round(z2,3))

z_krit=t.ppf(1-alpha/2,len(X)-2)/sqrt(len(X)-2+pow(t.ppf(1-alpha/2,len(X)-2),2))
# print (z_krit)

if abs(r_xy)>z_krit:
    print ("Так как",abs(round(r_xy,3)),">",round(z_krit,3),"то нулевая гипотеза принимается, следовательно между охватом населения вакцинации и заболеваемостью гриппом есть значимая линейиная корреляционная зависимость")
else:
    print ("Так как",abs(round(r_xy,3)),"<",round(z_krit,3),"то нулевая гипотеза отвергается следовательно между охватом населения вакцинации и заболеваемостью гриппом нет значимой линейиной корреляционная зависимость")

print ("\nЗадание №2")

b=sum_prod_dev/sum_sq_dev_X
a=mean_Y-b*mean_X
print ("a:",round(a,3))
print ("b:",round(b,3))

print("Вывод: уравнение линейной регресии имеет вид: y*(x)=",round(a,3),"+ (",round(b,3),"*x)")
print ("Коэфицент b=",round(b,3),"означает что при увеличении на 1% вакцинированных число заболевших будет уменьшаться на",abs(round(b,3)))

print ("При 15% y*=",round(a+b*15,3))
print ("При 200 заболевших процента вакцинированных будет равен",round((200-a)/b,3),"%")
sd=sqrt(((1-r_xy**2)*sum_sq_dev_Y)/((len(X)-2)*sum_sq_dev_X))
print ("Sd:",round(sd,3))
T=b/sd
print ("T:",round(T,3))

if abs(T)>=t.ppf(1-alpha/2,len(X)-2):
    print ("Так как",abs(T),">=",t.ppf(1-alpha/2,len(X)-2),"то нулевая гипотеза отвергается на принятом уровне альфа")
else:
    print ("Так как",abs(T),"<",t.ppf(1-alpha/2,len(X)-2),"то нулевая гипотеза принимается на принятом уровне альфа")

F=((r_xy**2)*(len(X)-2))/(1-r_xy**2)
print ("F:",round(F,3))
# print(f.ppf(1-alpha/2,1,len(X)-2))

if abs(F)>=f.ppf(1-alpha/2,1,len(X)-2):
    print("Так как",abs(F),">=",f.ppf(1-alpha/2,1,len(X)-2),"то нулевая гипотеза принимается на принятом уровне альфа")
else:
    print("Так как",abs(F),"<",f.ppf(1-alpha/2,1,len(X)-2),"то нулевая гипотеза отвергается на принятом уровне альфа")

y_x=[]
for x in X:
   y_x.append(round(a+b*x,3))

ey_x=[]
for y in Y:
    ey_x.append(round(y_x[i]-y,3))

table1 = PrettyTable()
table1.field_names = ["Xi", "Yi","y*xi","y*xi-y"]
for i in range(len(X)):
    table1.add_row([X[i],Y[i],y_x[i],ey_x[i]])
print (table1)


# График подбора с линиями
plt.figure(figsize=(10, 5))
plt.plot(X, Y, color='blue', marker='o', label='y*xi')
plt.plot(X, y_x, color='red', marker='o', label='yi')
plt.xlabel('Xi')
plt.ylabel('Yi')
plt.title('График подбора')
plt.legend()
plt.grid(True)

# График остатков с линиями
plt.figure(figsize=(10, 5))
plt.plot(X, ey_x, color='green', marker='o', linestyle='-')
plt.axhline(y=0, color='black', linestyle='--')
plt.title('График остатков')
plt.grid(True)
plt.show()